package com.aimei.www.moduel.util;


import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author xiah
 * @description 手机号和身份证验证
 */

public class PhoneAndIDcardCheckUtil {

       private static final String TELEPHONE = "^(13[0-9]|14[0-9]|15[0-9]|18[0-9]|17[0-9])\\d{8}$";
       // "^0?(13[0-9]|15[012356789]|17[013678]|18[0-9]|14[57])[0-9]{8}$";

       private static final Pattern PATTERN_TEL = Pattern.compile(TELEPHONE);

       /**
        * 城市代码
        */
       private static final List<String> CITY_CODE = Arrays.asList("11", "12", "13", "14", "15", "21", "22", "23",
               "31", "32", "33", "34",
               "35", "36", "37", "41", "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63",
               "64", "65", "71",
               "81", "82", "91");

       /**
        * 加权因子
        */
       private static final int[] POWER = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};

       public static boolean isTelephone(String mobilephone) {
              if ( StringUtils.isEmpty(mobilephone) ) {
                     return false;
              }
              Matcher matcher = PATTERN_TEL.matcher(mobilephone);
              return matcher.matches();
       }

       public static boolean isTelephones(List<String> noList) {
              if ( noList == null || noList.isEmpty() ) {
                     return false;
              }
              for ( String phone : noList ) {
                     if ( !isTelephone(phone) ) {
                            return false;
                     }
              }
              return true;
       }

       public static boolean ValidatedDcard(String idcard) {
              if ( idcard.length() == 15 ) {
                     return validate15IDCard(idcard);
              }
              return validate18Idcard(idcard);
       }

       private static boolean validate18Idcard(String idcard) {
              if ( !validateProvinceAndBirthday(idcard) ) {
                     return false;
              }
              String idcard17 = idcard.substring(0, 17);
              if ( !isDigital(idcard17) ) {
                     return false;
              }
              String idcard18Code = idcard.substring(17, 18);
              char c[] = idcard17.toCharArray();
              int bit[] = converCharToInt(c);
              int sum17 = 0;
              sum17 = getPowerSum(bit);
              // 将和值与11取模得到余数进行校验码判断
              String checkCode = getCheckCodeBySum(sum17);
              if ( null == checkCode ) {
                     return false;
              }
              // 将身份证的第18位与算出来的校码进行匹配，不相等就为假
              if ( !idcard18Code.equalsIgnoreCase(checkCode) ) {
                     return false;
              }

              return true;
       }

       private static int getPowerSum(int[] bit) {
              int sum = 0;

              if ( POWER.length != bit.length ) {
                     return sum;
              }

              for ( int i = 0; i < bit.length; i++ ) {
                     for ( int j = 0; j < POWER.length; j++ ) {
                            if ( i == j ) {
                                   sum = sum + bit[i] * POWER[j];
                            }
                     }
              }
              return sum;
       }

       private static boolean validateProvinceAndBirthday(String idcard) {
              if ( StringUtils.isEmpty(idcard) || (idcard.length() != 15 && idcard.length() != 18) ) {
                     return false;
              }
              String provinceId = idcard.substring(0, 2);
              // 校验省份
              if ( !CITY_CODE.contains(provinceId) ) {
                     return false;
              }
              String birthday = null;
              if ( idcard.length() == 15 ) {
                     if ( !isDigital(idcard) ) {
                            return false;
                     }
                     birthday = idcard.substring(6, 12);
              } else {
                     if ( !isDigital(idcard.substring(0, 17)) ) {
                            return false;
                     }
                     birthday = idcard.substring(6, 14);
              }
              SimpleDateFormat sdf = idcard.length() == 18 ? new SimpleDateFormat("yyyyMMdd") : new SimpleDateFormat
                      ("yyMMdd");
              try {
                     Date birthDate = sdf.parse(birthday);
                     String tmpDate = sdf.format(birthDate);
                     if ( !tmpDate.equals(birthday) ) {// 身份证日期错误
                            return false;
                     }
              } catch ( ParseException e1 ) {

                     return false;
              }

              return true;

       }

       private static boolean validate15IDCard(String idcard) {
              return validateProvinceAndBirthday(idcard);
       }

       private static boolean isDigital(String str) {
              return str.matches("^[0-9]*$");
       }

       private static int[] converCharToInt(char[] c) throws NumberFormatException {
              int[] a = new int[c.length];
              int k = 0;
              for ( char temp : c ) {
                     a[k++] = Integer.parseInt(String.valueOf(temp));
              }
              return a;
       }

       private static String getCheckCodeBySum(int sum17) {
              String checkCode = null;
              switch ( sum17 % 11 ) {
                     case 10:
                            checkCode = "2";
                            break;
                     case 9:
                            checkCode = "3";
                            break;
                     case 8:
                            checkCode = "4";
                            break;
                     case 7:
                            checkCode = "5";
                            break;
                     case 6:
                            checkCode = "6";
                            break;
                     case 5:
                            checkCode = "7";
                            break;
                     case 4:
                            checkCode = "8";
                            break;
                     case 3:
                            checkCode = "9";
                            break;
                     case 2:
                            checkCode = "x";
                            break;
                     case 1:
                            checkCode = "0";
                            break;
                     case 0:
                            checkCode = "1";
                            break;
              }
              return checkCode;
       }
}
